package com.cloud.custom.workflow.handler.common;

import java.util.Date;

import org.springframework.context.ApplicationContext;

import com.cloud.custom.common.utils.DateHelper;
import com.cloud.custom.workflow.bean.WfActDef;
import com.cloud.custom.workflow.command.WfRequest;
import com.cloud.custom.workflow.command.WfResponse;
import com.cloud.custom.workflow.command.create.CreateResponse;
import com.cloud.custom.workflow.command.rollback.RollbackResponse;
import com.cloud.custom.workflow.command.transit.TransitResponse;
import com.cloud.custom.workflow.entity.WfActInst;
import com.cloud.custom.workflow.enums.TimeStrategyEnum;
import com.cloud.custom.workflow.enums.TimeUnitEnum;
import com.cloud.custom.workflow.enums.TimeWarnLimitEnum;
import com.cloud.custom.workflow.handler.AfterHandler;
import com.cloud.custom.workflow.mapper.WfActInstMapper;
import com.cloud.custom.workflow.time.TimeCaclStrategy;
import com.cloud.custom.workflow.time.TimeCaclStrategyFactory;

/**
 * 环节计时
 * 
 * @author taominglong
 *
 */
public class ActTimeCalculationHandler extends AfterHandler {

	@Override
	public void afterHandler(WfRequest request, WfResponse resp, ApplicationContext context) {

		WfActInstMapper wfActInstMapper = context.getBean(WfActInstMapper.class);
		// 流程创建(计算)
		WfActInst inst = null;
		WfActDef actDef = null;
		if (resp instanceof CreateResponse) {
			CreateResponse createResp = (CreateResponse) resp;
			actDef = createResp.getActDef();
			inst = wfActInstMapper.selectByPrimaryKey(createResp.getActId());
			this.timeCacl(inst, actDef);
		}
		// 批转
		if (resp instanceof TransitResponse) {
			TransitResponse transResp = (TransitResponse) resp;
			actDef = transResp.getActDef();
			inst = wfActInstMapper.selectByPrimaryKey(transResp.getActId());
			this.timeCacl(inst, actDef);
		}
		// 回退
		if (resp instanceof RollbackResponse) {
			RollbackResponse rollbackResp = (RollbackResponse) resp;
			actDef = rollbackResp.getActDef();
			inst = wfActInstMapper.selectByPrimaryKey(rollbackResp.getActId());
			this.timeCacl(inst, actDef);

		}
		// 更新计算时间
		if(null != inst)
			wfActInstMapper.updateByPrimaryKeySelective(inst);

	}

	private void timeCacl(WfActInst inst, WfActDef actDef) {
		if (0 != actDef.getTimeStrategy()) {
			TimeCaclStrategy stratrgy = TimeCaclStrategyFactory
					.create(TimeStrategyEnum.getStrategy(actDef.getTimeStrategy()));
			TimeUnitEnum timeUnit = TimeUnitEnum.getUnit(actDef.getTimeUnitId());
			if (null != stratrgy && null != timeUnit) {
				// 环节警告时限， 环节截止时限
				inst.setWarnTimeMin(actDef.getWarnTime());
				inst.setWarnTimeChar(stratrgy.getTimeChar(actDef.getWarnTime(), timeUnit));
				inst.setWarnTime(stratrgy.getTimeAfterUnit(actDef.getWarnTime(), inst.getCreateTime(), timeUnit));

				inst.setLimitTimeMin(actDef.getLimitTime());
				inst.setLimitTimeChar(stratrgy.getTimeChar(actDef.getLimitTime(), timeUnit));
				inst.setLimitTime(stratrgy.getTimeAfterUnit(actDef.getLimitTime(), inst.getCreateTime(), timeUnit));

				// 流程的警告时限，流程的截止时限
				inst.setProcWarnTime(
						stratrgy.getTimeAfterUnit(actDef.getProcTimeWarn(), inst.getCreateTime(), timeUnit));
				inst.setProcLimitTime(
						stratrgy.getTimeAfterUnit(actDef.getProcTimeLimit(), inst.getCreateTime(), timeUnit));

				Date now = new Date();
				// 计算环节
				inst.setExpendTime(DateHelper.getMinutesBetween(inst.getCreateTime(), new Date()));
				inst.setExpendTimeChar(DateHelper.getTimeCharOfMinutes(inst.getExpendTime()));
				if (now.before(inst.getWarnTime())) {
					inst.setActTimeFlag(TimeWarnLimitEnum.NORMAL.getTimeWarnId());
				} else if (now.after(inst.getWarnTime()) && now.before(inst.getLimitTime())) {
					inst.setActTimeFlag(TimeWarnLimitEnum.WARN.getTimeWarnId());
				} else {
					inst.setActTimeFlag(TimeWarnLimitEnum.LIMIT.getTimeWarnId());
				}
				// 流程耗时
				if (null == inst.getProcExpendTime()) {
					inst.setProcExpendTime(0);
				}
				inst.setProcExpendTime(inst.getProcExpendTime() + inst.getExpendTime());
				inst.setProcExpendTimeChar(DateHelper.getTimeCharOfMinutes(inst.getProcExpendTime()));
				if (now.before(inst.getProcWarnTime())) {
					inst.setProcTimeFlag(TimeWarnLimitEnum.NORMAL.getTimeWarnId());
				} else if (now.after(inst.getProcWarnTime()) && now.before(inst.getProcLimitTime())) {
					inst.setProcTimeFlag(TimeWarnLimitEnum.WARN.getTimeWarnId());
				} else {
					inst.setProcTimeFlag(TimeWarnLimitEnum.LIMIT.getTimeWarnId());
				}
			}
		}
	}

}
